package com.hitemole.manager;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.XmlReader;
import com.badlogic.gdx.utils.XmlReader.Element;
import com.hitemole.game.GameCore;
import com.hitemole.levelObject.ComboBar;
import com.hitemole.levelObject.Moles;
import com.hitemole.levelObject.Scores;
import com.hitemole.objects.AnimatedGameObject;
import com.hitemole.objects.GameObject;
import com.hitemole.objects.InteractableGameObject;

public class GameManager {
	public static enum MULTIPLAYER_STATES{GOODGUY,BADGUY,END};
	public static enum GAME_STATES {
		GAME_START, GAME_PROGRESS, GAME_PAUSE, GAME_END, GAME_EXIT, GAME_RESUME, GAME_RESET
	};

	public static final int DEFAULT_SCREEN_WIDTH = 480;
	public static final int DEFAULT_SCREEN_HEIGHT = 800;
	public static final float ASPECT_RATIO = (float) DEFAULT_SCREEN_WIDTH
			/ (float) DEFAULT_SCREEN_HEIGHT;
	public static final String[] COUNTDOWN_STRING = { "1", "2", "3" };

	// game object;
	private ArrayList<Moles> molesList = new ArrayList<Moles>();
	private GameObject arcadeTable, background, comboBarFrame;
	private AnimatedGameObject hammer;
	private Scores score;
	private InteractableGameObject pauseButton;
	private ComboBar comboBar;
	private BitmapFont defaultSmallFont;
	private BitmapFont defaultBigFont;
	private Stage stageUI;
	private int lives = 3;

	private GAME_STATES gameState;
	private MULTIPLAYER_STATES multiplayerState;

	// object texture
	List<Map<String, Animation>> listOfMoleTexture = new ArrayList<Map<String, Animation>>();
	private Map<String, Animation> hammerTexture = new HashMap<String, Animation>();
	public String countDown = COUNTDOWN_STRING[2];
	// pause Menu Content
	private Table table;
	private TextButton resumeButton;
	private TextButton restartButton;
	private TextButton exitButton;
	private GameCore core;

	public GameManager(GameCore core) {
		this.core = core;
		this.gameState = GAME_STATES.GAME_START;
		float scaleX = (float) Gdx.graphics.getWidth() / DEFAULT_SCREEN_WIDTH;
		float scaleY = (float) Gdx.graphics.getHeight() / DEFAULT_SCREEN_HEIGHT;
		setupFont();
		setupMole(scaleX, scaleY);
		score = new Scores("the_true", 1);
		arcadeTable = new GameObject("ArcadeTable",
				core.getResourceManager().backgroundAsset.arcadeTexture,
				new Vector2(0, 0));
		background = new GameObject(
				"ArcadeBackground",
				core.getResourceManager().backgroundAsset.backgroundTexture,
				new Vector2(0, 0));
		pauseButton = new InteractableGameObject("pauseButton",
				core.getResourceManager().uiAsset.pauseButtonTexture,
				new Vector2(15, 730), scaleX, scaleY);
		hammer = new AnimatedGameObject("Hammer", hammerTexture, new Vector2(
				-300, -300), scaleX, scaleY);
		hammer.setAnimationKey("prok");

		comboBar = new ComboBar("Combo Bar",
				core.getResourceManager().uiAsset.comboBarTexture,
				new Vector2(88, 71));
		comboBarFrame = new GameObject("Combo Bar Frame",
				core.getResourceManager().uiAsset.comboBarFrameTexture,
				new Vector2(88, 71));

		table = new Table(core.getResourceManager().skinAsset.skin);
		table.setFillParent(true);
		resumeButton = new TextButton("Resume", core.getResourceManager().skinAsset.skin);
		resumeButton.addListener(new InputListener() {
			@Override
			public void touchUp(InputEvent event, float x, float y,
					int pointer, int button) {
				// TODO Auto-generated method stub
				setGameState(GAME_STATES.GAME_RESUME);
				resumeButton.setChecked(false);
				super.touchUp(event, x, y, pointer, button);
			}

			@Override
			public boolean touchDown(InputEvent event, float x, float y,
					int pointer, int button) {
				// TODO Auto-generated method stub
				return true;
			}
		});
		table.add(resumeButton).uniform().fill().spaceBottom(10);
		table.row();
		restartButton = new TextButton("Restart", core.getResourceManager().skinAsset.skin);
		restartButton.addListener(new InputListener() {
			@Override
			public void touchUp(InputEvent event, float x, float y,
					int pointer, int button) {
				// TODO Auto-generated method stub
				setGameState(GAME_STATES.GAME_RESET);
				restartButton.setChecked(false);
				Gdx.input.setInputProcessor(null);
				super.touchUp(event, x, y, pointer, button);
			}

			@Override
			public boolean touchDown(InputEvent event, float x, float y,
					int pointer, int button) {
				// TODO Auto-generated method stub
				return true;
			}
		});
		table.add(restartButton).uniform().fill().spaceBottom(10);
		table.row();
		exitButton = new TextButton("Main Menu", core.getResourceManager().skinAsset.skin);
		exitButton.addListener(new InputListener() {
			@Override
			public void touchUp(InputEvent event, float x, float y,
					int pointer, int button) {
				// TODO Auto-generated method stub
				GameManager.this.core.setScreen(GameManager.this.core.getMenuScreen());
				exitButton.setChecked(false);
				super.touchUp(event, x, y, pointer, button);
			}

			@Override
			public boolean touchDown(InputEvent event, float x, float y,
					int pointer, int button) {
				// TODO Auto-generated method stub
				return true;
			}
		});
		table.add(exitButton).uniform().fill().spaceBottom(10);
		table.row();
	}

	private void setupMole(float scaleX, float scaleY) {
		FileHandle moleXML = Gdx.files.internal("MoleObject.xml");
		XmlReader reader = new XmlReader();
		Element root = null;
		try {
			root = reader.parse(moleXML);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.err.println("Cannot parse XML");
		}
		Array<Element> moles = root.getChildrenByName("mole");
		loadTextures(moles.size);
		int x = 0;
		for (Element mole : moles) {
			String name = mole.getAttribute("name");
			int positionX = Integer.parseInt(mole.getChildByName("position")
					.getAttribute("x"));
			int positionY = Integer.parseInt(mole.getChildByName("position")
					.getAttribute("y"));
			molesList.add(new Moles(name, listOfMoleTexture.get(x),
					new Vector2(positionX, positionY), 0, scaleX, scaleY));
			x++;
		}
	}

	private void setupFont() {
		defaultBigFont = core.getResourceManager().fontAsset.bigFont;
		defaultSmallFont = core.getResourceManager().fontAsset.smallFont;
	}

	public BitmapFont getDefaultSmallFont() {
		return defaultSmallFont;
	}

	public BitmapFont getDefaultBigFont() {
		return defaultBigFont;
	}

	public GameObject getArcadeTable() {
		return arcadeTable;
	}

	public InteractableGameObject getPauseButton() {
		return pauseButton;
	}

	public GameObject getBackground() {
		return background;
	}

	public ArrayList<Moles> getMoles() {
		return molesList;
	}

	public Stage getStageUI() {
		return stageUI;
	}

	public AnimatedGameObject getHammer() {
		return hammer;
	}

	public Scores getScores() {
		return score;
	}

	public ComboBar getComboBar() {
		return comboBar;
	}

	public GameObject getComboBarFrame() {
		return comboBarFrame;
	}

	private void loadTextures(int mole) {
		// TODO Auto-generated method stub
		Map<String, Animation> animation = new HashMap<String, Animation>();
		for (int i = 0; i < mole; i++) {
			animation = new HashMap<String, Animation>();
			TextureRegion fullFrame[][] = new TextureRegion[mole][core.getResourceManager().moleAsset.fullFrame.length];
			TextureRegion halfFrame[][] = new TextureRegion[mole][core.getResourceManager().moleAsset.halfFrame.length];
			TextureRegion emptyFrame[][] = new TextureRegion[mole][core.getResourceManager().moleAsset.emptyFrame.length];
			for (int j = 0; j < 4; j++) {
				fullFrame[i][j] = new TextureRegion(core.getResourceManager().moleAsset.fullFrame[j]);
				if (j < 3) {
					halfFrame[i][j] = new TextureRegion(core.getResourceManager().moleAsset.halfFrame[j]);
				}
				if (j < 1) {
					emptyFrame[i][j] = new TextureRegion(core.getResourceManager().moleAsset.emptyFrame[j]);
				}
			}
			animation.put("full", new Animation(0.09f, fullFrame[i]));
			animation.put("half", new Animation(0.09f, halfFrame[i]));
			animation.put("empty", new Animation(0.09f, emptyFrame[i]));
			listOfMoleTexture.add(animation);
		}
		hammerTexture.put("prok", new Animation(0.05f, core.getResourceManager().hammerAsset.hammerFrames));
	}

	public TextureRegion getLivesTexture() {
		return core.getResourceManager().uiAsset.lifeTexture;
	}

	public GAME_STATES getGameState() {
		return gameState;
	}

	public void setGameState(GAME_STATES gameState) {
		this.gameState = gameState;
	}

	public void setStageUI(Stage stage) {
		// TODO Auto-generated method stub
		this.stageUI = stage;
	}

	public Table getTable() {
		// TODO Auto-generated method stub
		return table;
	}

	public int getLives() {
		return lives;
	}

	public void decreaseLives() {
		this.lives--;
	}
	
	public void goScoreScreen(){
		core.setScreen(core.getScoreScreen(score));
	}

	public MULTIPLAYER_STATES getMultiplayerState() {
		return multiplayerState;
	}

	public void setMultiplayerState(MULTIPLAYER_STATES multiplayerState) {
		this.multiplayerState = multiplayerState;
	}

	public void resetLives() {
		// TODO Auto-generated method stub
		this.lives=3;
	}
}
